/*======================= COPYRIGHT NOTICE ==================================*]
[* Copyright (c) 2020 Qualcomm Technologies, Inc.                            *]
[* All Rights Reserved.                                                      *]
[* Confidential and Proprietary - Qualcomm Technologies, Inc.                *]
[*===========================================================================*/

#include "math_lib.h"
#include "panic/panic.h"
#include "const_data/const_data.h"
#include "pmalloc/pl_malloc_preference.h"
#include "pmalloc/pl_malloc.h"
#include "string.h"
#include <audio_log/audio_log.h>

void vector_exp_kalimba(int *out, int *vec, int len, unsigned stride);
#define ln10 (2.3025850929940456840179914546844k)

void ml_linspace(int * out, int min, int max,int count)
{
    int diff = (max - min) << 8;   // increase resolution
    int blocks = count -1;
    int delta = diff / blocks;     // 17 cycles
    for (int i=0; i < count; ++i) {
        *out++ = min + ((i * delta)>>8);
    }
}

#define BY_LOG_10_BASE_2 (0.30102999566398119521373889472449k)
#define BY_LOG_e_BASE_2 (0.69314718055994530941723212145818k)

accum ml_log10(accum value)
{
    accum result = 0;
    if (value < 255k) {
        // The below sat fract value needs to be multiplied by 128
        sat fract log_value_base_2 = ml_log2(value);
        result = (log_value_base_2 * BY_LOG_10_BASE_2) << 7;
    }
    return result;
}

accum ml_ln(accum value)
{
    accum result = 0;
    if (value < 255k) {
        // The below sat fract value needs to be multiplied by 128
        sat fract log_value_base_2 = ml_log2(value);
        result = (log_value_base_2 * BY_LOG_e_BASE_2) << 7;
    }
    return result;
}

#define VECTOR_OP_STRIDE (1)

/**
 * exp(-n/16), n is in format 5:27, signed
 * vector_exp_kalimba is in q1.31
 */
void ml_exp(sat fract * out, const sat fract * vec, int len)
{
    // stride = 1
    int * out_ptr = (int *)out;
    const int * in_ptr = (const int *)vec;
    for (int i=0; i < len; ++i) {
        // each negative number gets converted to positive which ultimately becomes an index
        *out_ptr++ = __builtin_abs(*in_ptr++);
    }
    vector_exp_kalimba((int *)out, (int *)out, len, VECTOR_OP_STRIDE);
}

// pow10(x) defined as exp(ln(10)*x)
void ml_exp10(sat fract * out, const sat fract * in, int len)
{
    sat fract * out_ptr = out;
    const sat fract * in_ptr  = in;
    for (int i=0; i < len; ++i) {
        *out_ptr++ = (sat fract)(ln10 * (*in_ptr++));
    }
    ml_exp(out, out, len);
}

DMCONST sat fract ml_twiddle_real_ptr[EAI_TWIDDLE_SIZE] = {
#ifdef EAI_FFT_1024_POINT
    0.999999999534r, 0.0r, 0.7071067812r, -0.7071067812r, 0.9238795325r, -0.3826834324r, 0.3826834324r, -0.9238795325r,
    0.9807852804r, -0.195090322r, 0.555570233r, -0.8314696123r, 0.8314696123r, -0.555570233r, 0.195090322r, -0.9807852804r,
    0.9951847267r, -0.0980171403r, 0.6343932842r, -0.7730104534r, 0.8819212643r, -0.4713967368r, 0.2902846773r, -0.9569403357r,
    0.9569403357r, -0.2902846773r, 0.4713967368r, -0.8819212643r, 0.7730104534r, -0.6343932842r, 0.0980171403r, -0.9951847267r,
    0.9987954562r, -0.0490676743r, 0.6715589548r, -0.7409511254r, 0.9039892931r, -0.4275550934r, 0.3368898534r, -0.9415440652r,
    0.9700312532r, -0.2429801799r, 0.5141027442r, -0.85772861r, 0.8032075315r, -0.5956993045r, 0.1467304745r, -0.98917651r,
    0.98917651r, -0.1467304745r, 0.5956993045r, -0.8032075315r, 0.85772861r, -0.5141027442r, 0.2429801799r, -0.9700312532r,
    0.9415440652r, -0.3368898534r, 0.4275550934r, -0.9039892931r, 0.7409511254r, -0.6715589548r, 0.0490676743r, -0.9987954562r,
    0.9996988187r, -0.0245412285r, 0.6895405447r, -0.724247083r, 0.9142097557r, -0.405241314r, 0.3598950365r, -0.9329927988r,
    0.97570213r, -0.2191012402r, 0.5349976199r, -0.8448535652r, 0.8175848132r, -0.5758081914r, 0.1709618888r, -0.9852776424r,
    0.9924795346r, -0.1224106752r, 0.6152315906r, -0.7883464276r, 0.8700869911r, -0.4928981922r, 0.2667127575r, -0.9637760658r,
    0.9495281806r, -0.3136817404r, 0.4496113297r, -0.8932243012r, 0.7572088465r, -0.653172843r, 0.0735645636r, -0.9972904567r,
    0.9972904567r, -0.0735645636r, 0.653172843r, -0.7572088465r, 0.8932243012r, -0.4496113297r, 0.3136817404r, -0.9495281806r,
    0.9637760658r, -0.2667127575r, 0.4928981922r, -0.8700869911r, 0.7883464276r, -0.6152315906r, 0.1224106752r, -0.9924795346r,
    0.9852776424r, -0.1709618888r, 0.5758081914r, -0.8175848132r, 0.8448535652r, -0.5349976199r, 0.2191012402r, -0.97570213r,
    0.9329927988r, -0.3598950365r, 0.405241314r, -0.9142097557r, 0.724247083r, -0.6895405447r, 0.0245412285r, -0.9996988187r,
    0.9999247018r, -0.0122715383r, 0.6983762494r, -0.7157308253r, 0.9191138517r, -0.3939920401r, 0.371317194r, -0.9285060805r,
    0.9783173707r, -0.2071113762r, 0.5453249884r, -0.8382247056r, 0.8245893028r, -0.5657318108r, 0.183039888r, -0.9831054874r,
    0.99390697r, -0.1102222073r, 0.6248594881r, -0.7807372286r, 0.8760700942r, -0.4821837721r, 0.2785196894r, -0.9604305194r,
    0.9533060404r, -0.3020059493r, 0.460538711r, -0.8876396204r, 0.7651672656r, -0.6438315429r, 0.0857973123r, -0.9963126122r,
    0.9981181129r, -0.0613207363r, 0.6624157776r, -0.7491363945r, 0.8986744657r, -0.4386162385r, 0.3253102922r, -0.9456073254r,
    0.966976471r, -0.2548656596r, 0.5035383837r, -0.8639728561r, 0.7958369046r, -0.6055110414r, 0.1345807085r, -0.9909026354r,
    0.9873014182r, -0.1588581433r, 0.5857978575r, -0.8104571983r, 0.8513551931r, -0.5245896827r, 0.2310581083r, -0.9729399522r,
    0.9373390119r, -0.3484186802r, 0.4164295601r, -0.9091679831r, 0.7326542717r, -0.6806009978r, 0.0368072229r, -0.9993223846r,
    0.9993223846r, -0.0368072229r, 0.6806009978r, -0.7326542717r, 0.9091679831r, -0.4164295601r, 0.3484186802r, -0.9373390119r,
    0.9729399522r, -0.2310581083r, 0.5245896827r, -0.8513551931r, 0.8104571983r, -0.5857978575r, 0.1588581433r, -0.9873014182r,
    0.9909026354r, -0.1345807085r, 0.6055110414r, -0.7958369046r, 0.8639728561r, -0.5035383837r, 0.2548656596r, -0.966976471r,
    0.9456073254r, -0.3253102922r, 0.4386162385r, -0.8986744657r, 0.7491363945r, -0.6624157776r, 0.0613207363r, -0.9981181129r,
    0.9963126122r, -0.0857973123r, 0.6438315429r, -0.7651672656r, 0.8876396204r, -0.460538711r, 0.3020059493r, -0.9533060404r,
    0.9604305194r, -0.2785196894r, 0.4821837721r, -0.8760700942r, 0.7807372286r, -0.6248594881r, 0.1102222073r, -0.99390697r,
    0.9831054874r, -0.183039888r, 0.5657318108r, -0.8245893028r, 0.8382247056r, -0.5453249884r, 0.2071113762r, -0.9783173707r,
    0.9285060805r, -0.371317194r, 0.3939920401r, -0.9191138517r, 0.7157308253r, -0.6983762494r, 0.0122715383r, -0.9999247018r,
    0.9999811753r, -0.0061358846r, 0.7027547445r, -0.7114321957r, 0.9215140393r, -0.3883450467r, 0.3770074102r, -0.9262102421r,
    0.9795697657r, -0.2011046348r, 0.5504579729r, -0.834862875r, 0.8280450453r, -0.5606615762r, 0.1890686641r, -0.9819638691r,
    0.9945645707r, -0.1041216339r, 0.6296382389r, -0.7768884657r, 0.8790122264r, -0.4767992301r, 0.2844075372r, -0.9587034749r,
    0.9551411683r, -0.2961508882r, 0.4659764958r, -0.8847970984r, 0.7691033376r, -0.6391244449r, 0.0919089565r, -0.9957674145r,
    0.9984755806r, -0.0551952443r, 0.6669999223r, -0.7450577854r, 0.901348847r, -0.4330938189r, 0.3311063058r, -0.9435934582r,
    0.9685220943r, -0.2489276057r, 0.5088301425r, -0.8608669386r, 0.7995372691r, -0.6006164794r, 0.1406582393r, -0.9900582103r,
    0.9882575677r, -0.1527971853r, 0.5907597019r, -0.8068475535r, 0.8545579884r, -0.5193559902r, 0.237023606r, -0.971503891r,
    0.9394592236r, -0.3426607173r, 0.4220002708r, -0.9065957045r, 0.7368165689r, -0.6760927036r, 0.0429382569r, -0.9990777278r,
    0.9995294175r, -0.0306748032r, 0.6850836678r, -0.7284643904r, 0.911706032r, -0.4108431711r, 0.3541635254r, -0.9351835099r,
    0.9743393828r, -0.2250839114r, 0.5298036247r, -0.8481203448r, 0.8140363297r, -0.5808139581r, 0.1649131205r, -0.9863080972r,
    0.9917097537r, -0.1284981108r, 0.6103828063r, -0.7921065773r, 0.8670462455r, -0.498227667r, 0.2607941179r, -0.9653944417r,
    0.947585591r, -0.3195020308r, 0.4441221446r, -0.8959662498r, 0.753186799r, -0.6578066933r, 0.0674439196r, -0.9977230666r,
    0.9968202993r, -0.079682438r, 0.648514401r, -0.7612023855r, 0.8904487232r, -0.4550835871r, 0.30784964r, -0.951435021r,
    0.9621214043r, -0.2726213554r, 0.4875501601r, -0.8730949784r, 0.7845565972r, -0.6200572118r, 0.1163186309r, -0.9932119492r,
    0.9842100924r, -0.1770042204r, 0.5707807459r, -0.821102515r, 0.8415549774r, -0.5401714727r, 0.2131103199r, -0.9770281427r,
    0.9307669611r, -0.3656129978r, 0.3996241998r, -0.9166790599r, 0.720002508r, -0.6939714609r, 0.0184067299r, -0.9998305818r,
    0.9998305818r, -0.0184067299r, 0.6939714609r, -0.720002508r, 0.9166790599r, -0.3996241998r, 0.3656129978r, -0.9307669611r,
    0.9770281427r, -0.2131103199r, 0.5401714727r, -0.8415549774r, 0.821102515r, -0.5707807459r, 0.1770042204r, -0.9842100924r,
    0.9932119492r, -0.1163186309r, 0.6200572118r, -0.7845565972r, 0.8730949784r, -0.4875501601r, 0.2726213554r, -0.9621214043r,
    0.951435021r, -0.30784964r, 0.4550835871r, -0.8904487232r, 0.7612023855r, -0.648514401r, 0.079682438r, -0.9968202993r,
    0.9977230666r, -0.0674439196r, 0.6578066933r, -0.753186799r, 0.8959662498r, -0.4441221446r, 0.3195020308r, -0.947585591r,
    0.9653944417r, -0.2607941179r, 0.498227667r, -0.8670462455r, 0.7921065773r, -0.6103828063r, 0.1284981108r, -0.9917097537r,
    0.9863080972r, -0.1649131205r, 0.5808139581r, -0.8140363297r, 0.8481203448r, -0.5298036247r, 0.2250839114r, -0.9743393828r,
    0.9351835099r, -0.3541635254r, 0.4108431711r, -0.911706032r, 0.7284643904r, -0.6850836678r, 0.0306748032r, -0.9995294175r,
    0.9990777278r, -0.0429382569r, 0.6760927036r, -0.7368165689r, 0.9065957045r, -0.4220002708r, 0.3426607173r, -0.9394592236r,
    0.971503891r, -0.237023606r, 0.5193559902r, -0.8545579884r, 0.8068475535r, -0.5907597019r, 0.1527971853r, -0.9882575677r,
    0.9900582103r, -0.1406582393r, 0.6006164794r, -0.7995372691r, 0.8608669386r, -0.5088301425r, 0.2489276057r, -0.9685220943r,
    0.9435934582r, -0.3311063058r, 0.4330938189r, -0.901348847r, 0.7450577854r, -0.6669999223r, 0.0551952443r, -0.9984755806r,
    0.9957674145r, -0.0919089565r, 0.6391244449r, -0.7691033376r, 0.8847970984r, -0.4659764958r, 0.2961508882r, -0.9551411683r,
    0.9587034749r, -0.2844075372r, 0.4767992301r, -0.8790122264r, 0.7768884657r, -0.6296382389r, 0.1041216339r, -0.9945645707r,
    0.9819638691r, -0.1890686641r, 0.5606615762r, -0.8280450453r, 0.834862875r, -0.5504579729r, 0.2011046348r, -0.9795697657r,
    0.9262102421r, -0.3770074102r, 0.3883450467r, -0.9215140393r, 0.7114321957r, -0.7027547445r, 0.0061358846r, -0.9999811753r,
#else
    #error Twiddle data not defined
#endif
};

DMCONST sat fract ml_twiddle_imag_ptr[EAI_TWIDDLE_SIZE] = {
#ifdef EAI_FFT_1024_POINT
    0.0r, -1.0r, -0.7071067812r, -0.7071067812r, -0.3826834324r, -0.9238795325r, -0.9238795325r, -0.3826834324r,
    -0.195090322r, -0.9807852804r, -0.8314696123r, -0.555570233r, -0.555570233r, -0.8314696123r, -0.9807852804r, -0.195090322r,
    -0.0980171403r, -0.9951847267r, -0.7730104534r, -0.6343932842r, -0.4713967368r, -0.8819212643r, -0.9569403357r, -0.2902846773r,
    -0.2902846773r, -0.9569403357r, -0.8819212643r, -0.4713967368r, -0.6343932842r, -0.7730104534r, -0.9951847267r, -0.0980171403r,
    -0.0490676743r, -0.9987954562r, -0.7409511254r, -0.6715589548r, -0.4275550934r, -0.9039892931r, -0.9415440652r, -0.3368898534r,
    -0.2429801799r, -0.9700312532r, -0.85772861r, -0.5141027442r, -0.5956993045r, -0.8032075315r, -0.98917651r, -0.1467304745r,
    -0.1467304745r, -0.98917651r, -0.8032075315r, -0.5956993045r, -0.5141027442r, -0.85772861r, -0.9700312532r, -0.2429801799r,
    -0.3368898534r, -0.9415440652r, -0.9039892931r, -0.4275550934r, -0.6715589548r, -0.7409511254r, -0.9987954562r, -0.0490676743r,
    -0.0245412285r, -0.9996988187r, -0.724247083r, -0.6895405447r, -0.405241314r, -0.9142097557r, -0.9329927988r, -0.3598950365r,
    -0.2191012402r, -0.97570213r, -0.8448535652r, -0.5349976199r, -0.5758081914r, -0.8175848132r, -0.9852776424r, -0.1709618888r,
    -0.1224106752r, -0.9924795346r, -0.7883464276r, -0.6152315906r, -0.4928981922r, -0.8700869911r, -0.9637760658r, -0.2667127575r,
    -0.3136817404r, -0.9495281806r, -0.8932243012r, -0.4496113297r, -0.653172843r, -0.7572088465r, -0.9972904567r, -0.0735645636r,
    -0.0735645636r, -0.9972904567r, -0.7572088465r, -0.653172843r, -0.4496113297r, -0.8932243012r, -0.9495281806r, -0.3136817404r,
    -0.2667127575r, -0.9637760658r, -0.8700869911r, -0.4928981922r, -0.6152315906r, -0.7883464276r, -0.9924795346r, -0.1224106752r,
    -0.1709618888r, -0.9852776424r, -0.8175848132r, -0.5758081914r, -0.5349976199r, -0.8448535652r, -0.97570213r, -0.2191012402r,
    -0.3598950365r, -0.9329927988r, -0.9142097557r, -0.405241314r, -0.6895405447r, -0.724247083r, -0.9996988187r, -0.0245412285r,
    -0.0122715383r, -0.9999247018r, -0.7157308253r, -0.6983762494r, -0.3939920401r, -0.9191138517r, -0.9285060805r, -0.371317194r,
    -0.2071113762r, -0.9783173707r, -0.8382247056r, -0.5453249884r, -0.5657318108r, -0.8245893028r, -0.9831054874r, -0.183039888r,
    -0.1102222073r, -0.99390697r, -0.7807372286r, -0.6248594881r, -0.4821837721r, -0.8760700942r, -0.9604305194r, -0.2785196894r,
    -0.3020059493r, -0.9533060404r, -0.8876396204r, -0.460538711r, -0.6438315429r, -0.7651672656r, -0.9963126122r, -0.0857973123r,
    -0.0613207363r, -0.9981181129r, -0.7491363945r, -0.6624157776r, -0.4386162385r, -0.8986744657r, -0.9456073254r, -0.3253102922r,
    -0.2548656596r, -0.966976471r, -0.8639728561r, -0.5035383837r, -0.6055110414r, -0.7958369046r, -0.9909026354r, -0.1345807085r,
    -0.1588581433r, -0.9873014182r, -0.8104571983r, -0.5857978575r, -0.5245896827r, -0.8513551931r, -0.9729399522r, -0.2310581083r,
    -0.3484186802r, -0.9373390119r, -0.9091679831r, -0.4164295601r, -0.6806009978r, -0.7326542717r, -0.9993223846r, -0.0368072229r,
    -0.0368072229r, -0.9993223846r, -0.7326542717r, -0.6806009978r, -0.4164295601r, -0.9091679831r, -0.9373390119r, -0.3484186802r,
    -0.2310581083r, -0.9729399522r, -0.8513551931r, -0.5245896827r, -0.5857978575r, -0.8104571983r, -0.9873014182r, -0.1588581433r,
    -0.1345807085r, -0.9909026354r, -0.7958369046r, -0.6055110414r, -0.5035383837r, -0.8639728561r, -0.966976471r, -0.2548656596r,
    -0.3253102922r, -0.9456073254r, -0.8986744657r, -0.4386162385r, -0.6624157776r, -0.7491363945r, -0.9981181129r, -0.0613207363r,
    -0.0857973123r, -0.9963126122r, -0.7651672656r, -0.6438315429r, -0.460538711r, -0.8876396204r, -0.9533060404r, -0.3020059493r,
    -0.2785196894r, -0.9604305194r, -0.8760700942r, -0.4821837721r, -0.6248594881r, -0.7807372286r, -0.99390697r, -0.1102222073r,
    -0.183039888r, -0.9831054874r, -0.8245893028r, -0.5657318108r, -0.5453249884r, -0.8382247056r, -0.9783173707r, -0.2071113762r,
    -0.371317194r, -0.9285060805r, -0.9191138517r, -0.3939920401r, -0.6983762494r, -0.7157308253r, -0.9999247018r, -0.0122715383r,
    -0.0061358846r, -0.9999811753r, -0.7114321957r, -0.7027547445r, -0.3883450467r, -0.9215140393r, -0.9262102421r, -0.3770074102r,
    -0.2011046348r, -0.9795697657r, -0.834862875r, -0.5504579729r, -0.5606615762r, -0.8280450453r, -0.9819638691r, -0.1890686641r,
    -0.1041216339r, -0.9945645707r, -0.7768884657r, -0.6296382389r, -0.4767992301r, -0.8790122264r, -0.9587034749r, -0.2844075372r,
    -0.2961508882r, -0.9551411683r, -0.8847970984r, -0.4659764958r, -0.6391244449r, -0.7691033376r, -0.9957674145r, -0.0919089565r,
    -0.0551952443r, -0.9984755806r, -0.7450577854r, -0.6669999223r, -0.4330938189r, -0.901348847r, -0.9435934582r, -0.3311063058r,
    -0.2489276057r, -0.9685220943r, -0.8608669386r, -0.5088301425r, -0.6006164794r, -0.7995372691r, -0.9900582103r, -0.1406582393r,
    -0.1527971853r, -0.9882575677r, -0.8068475535r, -0.5907597019r, -0.5193559902r, -0.8545579884r, -0.971503891r, -0.237023606r,
    -0.3426607173r, -0.9394592236r, -0.9065957045r, -0.4220002708r, -0.6760927036r, -0.7368165689r, -0.9990777278r, -0.0429382569r,
    -0.0306748032r, -0.9995294175r, -0.7284643904r, -0.6850836678r, -0.4108431711r, -0.911706032r, -0.9351835099r, -0.3541635254r,
    -0.2250839114r, -0.9743393828r, -0.8481203448r, -0.5298036247r, -0.5808139581r, -0.8140363297r, -0.9863080972r, -0.1649131205r,
    -0.1284981108r, -0.9917097537r, -0.7921065773r, -0.6103828063r, -0.498227667r, -0.8670462455r, -0.9653944417r, -0.2607941179r,
    -0.3195020308r, -0.947585591r, -0.8959662498r, -0.4441221446r, -0.6578066933r, -0.753186799r, -0.9977230666r, -0.0674439196r,
    -0.079682438r, -0.9968202993r, -0.7612023855r, -0.648514401r, -0.4550835871r, -0.8904487232r, -0.951435021r, -0.30784964r,
    -0.2726213554r, -0.9621214043r, -0.8730949784r, -0.4875501601r, -0.6200572118r, -0.7845565972r, -0.9932119492r, -0.1163186309r,
    -0.1770042204r, -0.9842100924r, -0.821102515r, -0.5707807459r, -0.5401714727r, -0.8415549774r, -0.9770281427r, -0.2131103199r,
    -0.3656129978r, -0.9307669611r, -0.9166790599r, -0.3996241998r, -0.6939714609r, -0.720002508r, -0.9998305818r, -0.0184067299r,
    -0.0184067299r, -0.9998305818r, -0.720002508r, -0.6939714609r, -0.3996241998r, -0.9166790599r, -0.9307669611r, -0.3656129978r,
    -0.2131103199r, -0.9770281427r, -0.8415549774r, -0.5401714727r, -0.5707807459r, -0.821102515r, -0.9842100924r, -0.1770042204r,
    -0.1163186309r, -0.9932119492r, -0.7845565972r, -0.6200572118r, -0.4875501601r, -0.8730949784r, -0.9621214043r, -0.2726213554r,
    -0.30784964r, -0.951435021r, -0.8904487232r, -0.4550835871r, -0.648514401r, -0.7612023855r, -0.9968202993r, -0.079682438r,
    -0.0674439196r, -0.9977230666r, -0.753186799r, -0.6578066933r, -0.4441221446r, -0.8959662498r, -0.947585591r, -0.3195020308r,
    -0.2607941179r, -0.9653944417r, -0.8670462455r, -0.498227667r, -0.6103828063r, -0.7921065773r, -0.9917097537r, -0.1284981108r,
    -0.1649131205r, -0.9863080972r, -0.8140363297r, -0.5808139581r, -0.5298036247r, -0.8481203448r, -0.9743393828r, -0.2250839114r,
    -0.3541635254r, -0.9351835099r, -0.911706032r, -0.4108431711r, -0.6850836678r, -0.7284643904r, -0.9995294175r, -0.0306748032r,
    -0.0429382569r, -0.9990777278r, -0.7368165689r, -0.6760927036r, -0.4220002708r, -0.9065957045r, -0.9394592236r, -0.3426607173r,
    -0.237023606r, -0.971503891r, -0.8545579884r, -0.5193559902r, -0.5907597019r, -0.8068475535r, -0.9882575677r, -0.1527971853r,
    -0.1406582393r, -0.9900582103r, -0.7995372691r, -0.6006164794r, -0.5088301425r, -0.8608669386r, -0.9685220943r, -0.2489276057r,
    -0.3311063058r, -0.9435934582r, -0.901348847r, -0.4330938189r, -0.6669999223r, -0.7450577854r, -0.9984755806r, -0.0551952443r,
    -0.0919089565r, -0.9957674145r, -0.7691033376r, -0.6391244449r, -0.4659764958r, -0.8847970984r, -0.9551411683r, -0.2961508882r,
    -0.2844075372r, -0.9587034749r, -0.8790122264r, -0.4767992301r, -0.6296382389r, -0.7768884657r, -0.9945645707r, -0.1041216339r,
    -0.1890686641r, -0.9819638691r, -0.8280450453r, -0.5606615762r, -0.5504579729r, -0.834862875r, -0.9795697657r, -0.2011046348r,
    -0.3770074102r, -0.9262102421r, -0.9215140393r, -0.3883450467r, -0.7027547445r, -0.7114321957r, -0.9999811753r, -0.0061358846r,
#else
    #error Twiddle data not defined
#endif
};

static sat fract * ml_twiddle_real_ptr_ram;
static sat fract * ml_twiddle_imag_ptr_ram;

asm int ml_get_fft_num_points(void)
{
//  @{} = M[$fft.NUM_POINTS];
    @{} = $fft.NUM_POINTS;
}

asm int ml_get_twiddle_real_address(void)
{
  @{} = M[$fft.twiddle_real_address];
}

asm int ml_get_twiddle_imag_address(void)
{
  @{} = M[$fft.twiddle_imag_address];
}

void ml_twiddle_init(int num_points) {
    if (!ml_twiddle_real_ptr_ram && !ml_twiddle_imag_ptr_ram){
        int size_required = EAI_TWIDDLE_SIZE << 2;
        ml_twiddle_real_ptr_ram = (sat fract*)xzppmalloc(size_required, MALLOC_PREFERENCE_DM1);
        if (!ml_twiddle_real_ptr_ram)
        {
            panic_diatribe(PANIC_HYDRA_PRIVATE_MEMORY_EXHAUSTION, size_required);
        }
        ml_twiddle_imag_ptr_ram = (sat fract*)xzppmalloc(size_required, MALLOC_PREFERENCE_DM2);
        if (!ml_twiddle_imag_ptr_ram)
        {
            panic_diatribe(PANIC_HYDRA_PRIVATE_MEMORY_EXHAUSTION, size_required);
        }
        memcpy(ml_twiddle_real_ptr_ram, ml_twiddle_real_ptr, size_required);
        memcpy(ml_twiddle_imag_ptr_ram, ml_twiddle_imag_ptr, size_required);
    }
}

void ml_twiddle_release(void)
{
    if (ml_twiddle_real_ptr_ram) {
        pfree(ml_twiddle_real_ptr_ram);
        ml_twiddle_real_ptr_ram = NULL;
    }
    if (ml_twiddle_imag_ptr_ram) {
        pfree(ml_twiddle_imag_ptr_ram);
        ml_twiddle_imag_ptr_ram = NULL;
    }
}

void ml_fft( tFFTStruct *fft_struct)
{
    // Get the existing values
    int ml_fft_num_points = ml_get_fft_num_points();
    int * ml_fft_twiddle_real = (int *)ml_get_twiddle_real_address();
    int * ml_fft_twiddle_imag = (int *)ml_get_twiddle_imag_address();
    // replace with eai's values
    ml_twiddle_load(fft_struct->numPoints, (int *)ml_twiddle_real_ptr_ram, (int *)ml_twiddle_imag_ptr_ram);
    // do fft
    fft(fft_struct);
    // reset to previous values
    ml_twiddle_load(ml_fft_num_points, ml_fft_twiddle_real, ml_fft_twiddle_imag);
}


